using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Modelica.Annotations;



namespace DrawToolsLib {
    /// <summary>
    ///  Text graphics object.
    /// </summary>
    public class GraphicsText : GraphicsRectangleBase {
        #region Class Members

        private Text src; // Modelica Text

        private FontStyle textFontStyle;
        private FontWeight textFontWeight;
        private FontStretch textFontStretch;

        // For internal use
        FormattedText formattedText;

        #endregion Class Members

        #region Constructors

        public GraphicsText(Text src) {
            if (src != null) {
                this.src = src;
            } else {
                this.src = new Text();
            }
            this.graphicsActualScale = 1.0;
        }

        public GraphicsText()
            : this(new Text()) {
        }

        public GraphicsText(
            string text,
            double left,
            double top,
            double right,
            double bottom,
            Color objectColor,
            double textFontSize,
            string textFontFamilyName,
            FontStyle textFontStyle,
            FontWeight textFontWeight,
            FontStretch textFontStretch,
            double actualScale,
            CoordinateSystem cs)
            : this() {
            this.ParentCS = cs;
            this.Text = text;
            this.rectangleLeft = left;
            this.rectangleTop = top;
            this.rectangleRight = right;
            this.rectangleBottom = bottom;
            this.graphicsObjectColor = objectColor;
            this.TextFontSize = textFontSize;
            this.TextFontFamilyName = textFontFamilyName;
            this.textFontStyle = textFontStyle;
            this.textFontWeight = textFontWeight;
            this.textFontStretch = textFontStretch;
            this.graphicsActualScale = actualScale;

            graphicsLineWidth = 2;      // used for drawing bounding rectangle when selected
        }

        //public GraphicsText()
        //    :
        //    this(Properties.Settings.Default.UnknownText, 0, 0, 0, 0, Colors.Black, 12, 
        //         Properties.Settings.Default.DefaultFontFamily, FontStyles.Normal,
        //         FontWeights.Normal, FontStretches.Normal, 1.0)
        //{
        //}

        #endregion Constructors

        #region Properties

        //{{x1, y1}, {x2, y2}}";
        protected override double rectangleLeft {
            get {
                return src.Extent.X1 - ex.X1;
            }
            set {
                src.Extent.X1 = value + ex.X1;
            }
        }

        protected override double rectangleTop {
            get {
                return ex.Y2 - src.Extent.Y1;
            }
            set {
                src.Extent.Y1 = ex.Y2 - value;
            }
        }

        protected override double rectangleRight {
            get {
                return src.Extent.X2 - ex.X1;
            }
            set {
                src.Extent.X2 = value + ex.X1;
            }
        }

        protected override double rectangleBottom {
            get {
                return ex.Y2 - src.Extent.Y2;
            }
            set {
                src.Extent.Y2 = ex.Y2 - value;
            }
        }

        protected override Color graphicsObjectColor {
            get {
                return Color.FromRgb(src.LineColor.R, src.LineColor.G, src.LineColor.B);
            }
            set {
                src.LineColor = value;
                RefreshDrawing();
            }
        }

        public string Text {
            get {
                return src.TextString;
            }
            set {
                src.TextString = value;
                RefreshDrawing();
            }
        }

        public string TextFontFamilyName {
            get {
                return src.FontName;
            }
            set {
                src.FontName = value;
                RefreshDrawing();
            }
        }

        public FontStyle TextFontStyle {
            get {
                return textFontStyle;
            }
            set {
                textFontStyle = value;
                RefreshDrawing();
            }
        }

        public FontWeight TextFontWeight {
            get {
                return textFontWeight;
            }
            set {
                textFontWeight = value;
                RefreshDrawing();
            }
        }

        public FontStretch TextFontStretch {
            get {
                return textFontStretch;
            }
            set {
                textFontStretch = value;
                RefreshDrawing();
            }
        }

        public double TextFontSize {
            get {
                return src.FontSize;
            }
            set {
                src.FontSize = value;
                RefreshDrawing();
            }
        }

        public override GraphicItem Source {
            get {
                return src;
            }
        }

        #endregion Properties

        #region Overrides

        /// <summary>
        /// Draw text
        /// </summary>
        public override void Draw(DrawingContext drawingContext) {
            if (drawingContext == null) {
                throw new ArgumentNullException("drawingContext");
            }

            CreateFormattedText();

            Rect rect = Rectangle;

            drawingContext.PushClip(new RectangleGeometry(rect));

            drawingContext.DrawText(formattedText, new Point(rect.Left, rect.Top));

            drawingContext.Pop();

            if (IsSelected) {
                drawingContext.DrawRectangle(
                    null,
                    new Pen(new SolidColorBrush(graphicsObjectColor), ActualLineWidth),
                    rect);
            }

            // Draw tracker
            base.Draw(drawingContext);
        }

        /// <summary>
        /// Update rectangle to fit actual text size.
        /// </summary>
        public void UpdateRectangle() {
            /*
             * 
             * Trying to find acceptable adjustment algorithm, I decided finally
             * to leave rectangle completely under user control.
            
            CreateFormattedText();

            Rect rect = Rectangle;

            if (formattedText.Width > rect.Width)
            {
                formattedText.MaxTextWidth = rect.Width;
            }
            else
            {
                rect.Width = formattedText.Width;
            }

            if (rect.Height > formattedText.Height)
            {
                rect.Height = formattedText.Height;
            }

            this.left = rect.Left;
            this.top = rect.Top;
            this.right = rect.Right;
            this.bottom = rect.Bottom;
             */

            RefreshDrawing();

        }

        /// <summary>
        /// Create formatted text.
        /// It is required for drawing and updating bounding rectangle.
        /// </summary>
        void CreateFormattedText() {
            // Number of corrections I have done after trying to open
            // XML file with correct object names, but incorrect field names.
            if (String.IsNullOrEmpty(TextFontFamilyName)) {
                TextFontFamilyName = Properties.Settings.Default.DefaultFontFamily;
            }

            if (Text == null) {
                Text = "";
            }

            if (TextFontSize <= 0.0) {
                TextFontSize = 12.0;
            }

            Typeface typeface = new Typeface(
                new FontFamily(TextFontFamilyName),
                textFontStyle,
                textFontWeight,
                textFontStretch);

            formattedText = new FormattedText(
                Text,
                System.Globalization.CultureInfo.InvariantCulture,
                FlowDirection.LeftToRight,
                typeface,
                TextFontSize,
                new SolidColorBrush(graphicsObjectColor));

            formattedText.MaxTextWidth = Rectangle.Width;
        }

        /// <summary>
        /// Test whether object contains point
        /// </summary>
        public override bool Contains(Point point) {
            return this.Rectangle.Contains(point);
        }
        
        public override object Clone() {
            GraphicsText g = new GraphicsText((Text)this.src.Clone());
            g.selected = this.selected;
            g.ActualScale = this.ActualScale;
            return g;
        }

        #endregion Overrides
    }
}
